package com.hzlj.position.locate.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fz.common.base.core.DistanceUtils;
import com.fz.common.base.core.date.DateUtils;
import com.fz.common.base.dto.PageParamDTO;
import com.fz.common.base.dto.QueryPageResultDTO;
import com.fz.common.dict.annotation.DictConvert;
import com.google.common.collect.Maps;
import com.hzlj.common.message.common.dto.message.MessageNoticeUserDTO;
import com.hzlj.common.message.common.util.MessageRestUtil;
import com.hzlj.position.config.common.dto.common.PositionCommonDTO;
import com.hzlj.position.config.common.dto.jzJbxxConfig.JzJbxxConfigQueryResultDTO;
import com.hzlj.position.config.service.JzJbxxConfigService;
import com.hzlj.position.config.service.NoticeConfigService;
import com.hzlj.position.locate.common.dto.abnNightOut.AbnNightOutListDTO;
import com.hzlj.position.locate.common.dto.abnNightOut.AbnNightOutQueryParamDTO;
import com.hzlj.position.locate.common.dto.abnNightOutJzry.AbnNightOutJzryAddDTO;
import com.hzlj.position.locate.common.model.AbnNightOut;
import com.hzlj.position.locate.dao.AbnNightOutDao;
import com.hzlj.position.locate.service.AbnNightOutJzryService;
import com.hzlj.position.locate.service.AbnNightOutService;
import com.hzlj.position.locate.service.PositionService;
import com.hzlj.sqjz.config.common.enums.JgLscj;
import com.hzlj.sqjz.system.service.JgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.hzlj.position.config.config.IdConfig.POSITION_ID_GEN;

/**
 * 定位分析-夜不归宿表(AbnNightOut)表服务接口
 *
 * @author lifh
 * @date 2023-03-28 10:20:28
 */
@Slf4j
@Service
public class AbnNightOutServiceImpl implements AbnNightOutService {
    /**
     * 离家距离
     */
    private final static Integer DISTANCE_FROM_HOME = 2000;
    @Resource
    private AbnNightOutDao abnNightOutDao;
    @Resource
    private AbnNightOutJzryService abnNightOutJzryService;
    @Resource
    private PositionService positionService;
    @Resource
    private JzJbxxConfigService jzJbxxConfigService;
    @Resource
    private JgService jgService;
    @Resource
    private NoticeConfigService noticeConfigService;

    /**
     * 夜不归宿分析
     * 22点-6点，居住地坐标点2公里范围内无位置信息
     */
    @Override
    public void abn() {
        Date startTime = DateUtils.parseDate(DateUtils.formatDate(DateUtils.yesterday(), "yyyy-MM-dd") + " 23:00:00");
        Date endTime = DateUtils.parseDate(DateUtils.formatDate("yyyy-MM-dd") + " 06:00:00");
        List<String> jgCodes = jgService.jgCodesByLscj(null, JgLscj.CITY.getCode(), null);
        log.info("获取机构数[夜不归宿]:size={}", jgCodes.size());
        for (String jgCode : jgCodes) {
            List<PositionCommonDTO> positions = positionService.listPosition4Abn(jgCode, startTime, endTime);
            log.info("获取位置数量[夜不归宿]:size={},jgCode={},startTime={},endTime={}", positions.size(), jgCode, startTime, endTime);
            if (ObjectUtil.isEmpty(positions)) {
                continue;
            }
            Map<String, List<PositionCommonDTO>> positionsGroup = positions.stream().collect(Collectors.groupingBy(PositionCommonDTO::getJzId));
            for (Map.Entry<String, List<PositionCommonDTO>> entry : positionsGroup.entrySet()) {
                String jzId = entry.getKey();
                JzJbxxConfigQueryResultDTO jzJbxx = this.jzJbxxConfigService.getJzJbxxConfigByJzId(jzId);
                if (jzJbxx == null
                        || ObjectUtil.isEmpty(jzJbxx.getHomeLatitude())
                        || ObjectUtil.isEmpty(jzJbxx.getHomeLongitude())) {
                    log.warn("夜不归宿分析，请预先配置居住地坐标：{}", jzId);
                    continue;
                }

                //离家距离
                List<AbnNightOutJzryAddDTO> filterPositions = entry.getValue().stream().map(e -> {
                    double distance = DistanceUtils
                            .amapDistance(Double.parseDouble(jzJbxx.getHomeLongitude()), Double.parseDouble(jzJbxx.getHomeLatitude()), Double.parseDouble(e.getLongitude()), Double.parseDouble(e.getLatitude()));
                    if (distance <= DISTANCE_FROM_HOME) {
                        return null;
                    }
                    AbnNightOutJzryAddDTO position = BeanUtil.copyProperties(e, AbnNightOutJzryAddDTO.class);
                    position.setDistance(new BigDecimal(distance));
                    return position;
                }).filter(Objects::nonNull).collect(Collectors.toList());

                //全部在2000米之外
                if (entry.getValue().size() == filterPositions.size()) {
                    saveAbnNightOuts(
                            jzId,
                            startTime,
                            endTime,
                            filterPositions);
                }
            }
        }
    }


    private void saveAbnNightOuts(String jzId,
                                  Date startTime,
                                  Date endTime,
                                  List<AbnNightOutJzryAddDTO> dtos) {
        AbnNightOut abn = new AbnNightOut();
        abn.setId(POSITION_ID_GEN.nextIdStr());
        abn.setJzId(jzId);
        abn.setStartTime(startTime);
        abn.setEndTime(endTime);
        abn.setPositionsNum(dtos.size());
        abn.setCreateTime(new Date());
        abn.setMaxDistance(dtos.stream().map(AbnNightOutJzryAddDTO::getDistance).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO));
        //保存
        abnNightOutDao.save(abn);
        //保存明细
        abnNightOutJzryService.saveAbnNightOutJzry(abn.getId(), dtos);
        //发送通知
        noticeGzry(dtos.get(0));
    }

    /**
     * 查询列表：分页
     */
    @Override
    @DictConvert
    public QueryPageResultDTO<AbnNightOutListDTO> pageAbnNightOut(AbnNightOutQueryParamDTO dto, PageParamDTO page) {
        return this.abnNightOutDao.pageAbnNightOut(dto, page);
    }

    private void noticeGzry(AbnNightOutJzryAddDTO jzJbxx) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("jzryXm", jzJbxx.getXm());
        params.put("abnTypeText", "夜不归宿");
        params.put("positionTime", DateUtil.formatDate(jzJbxx.getPositionTime()));
        MessageRestUtil.noticeQueryUsers(
                "abn-night-out-gzry",
                jzJbxx.getId(),
                params,
                MessageNoticeUserDTO.of(true, jzJbxx.getJgCode(), noticeConfigService.defaultMessageNoticeAuths(jzJbxx.getJgCode()))
        );
    }
}
